package com.maiji.cloud.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.OptionalInt;
import java.util.Random;
import java.util.function.IntBinaryOperator;

/**
 * 
 * Description:  
 * @author zhanglr  
 * @date 2019年6月26日
 */
public class Arith {

	/**
	 * 加法
	 *
	 * @param dot
	 *            保留小数点
	 * @param numbers
	 *            数字类型
	 * @return
	 */
	public static double add(int dot, Number... numbers) {
		return getAirth(dot, AirthType.ADD.getValue(), numbers);

	}

	/**
	 * 减法
	 *
	 * @param dot
	 *            保留小数点
	 * @param numbers
	 *            第一个是减数
	 * @return
	 */
	public static double subtract(int dot, Number... numbers) {

		return getAirth(dot, AirthType.SUBTRACT.getValue(), numbers);

	}

	/**
	 * 乘法
	 *
	 * @param dot
	 *            保留小数点
	 * @param numbers
	 *            乘法的因子
	 * @return
	 */
	public static double multiplys(int dot, Number... numbers) {

		return getAirth(dot, AirthType.MULTIPLY.getValue(), numbers);

	}

	/**
	 * 除法
	 *
	 * @param dot
	 *            保留小数点
	 * @param numbers
	 *            除数，第一个是除数
	 * @return
	 */
	public static double divides(int dot, Number... numbers) {

		return getAirth(dot, AirthType.DIVIDE.getValue(), numbers);

	}

	/**
	 * 设置小数点保留几位
	 *
	 */
	public static double setScale(Double x1, int scale) {
		return BigDecimal.valueOf(x1).setScale(scale, RoundingMode.HALF_UP).doubleValue();
	}

	/**
	 * 综合的运算
	 *
	 * @param dot
	 *            保留精度
	 * @param airthType
	 *            运算的类型
	 * @param numbers
	 *            需要运算的数字
	 * @return
	 */
	private static double getAirth(int dot, int airthType, Number... numbers) {

		if (numbers == null || numbers.length == 0) {
			return 0.0;
		}
		BigDecimal bigDecimal = new BigDecimal(String.valueOf(numbers[0]));

		for (int i = 1; i < numbers.length; i++) {
			switch (airthType) {
			case 0:
				bigDecimal = bigDecimal.add(new BigDecimal(String.valueOf(numbers[i])));
				break;
			case 1:
				bigDecimal = bigDecimal.divide(new BigDecimal(String.valueOf(numbers[i])), dot, RoundingMode.HALF_UP);
				break;
			case 2:
				bigDecimal = bigDecimal.subtract(new BigDecimal(String.valueOf(numbers[i])));
				break;
			case 3:
				bigDecimal = bigDecimal.multiply(new BigDecimal(String.valueOf(numbers[i])));
				break;
			}
		}
		return bigDecimal.setScale(dot, RoundingMode.HALF_UP).doubleValue();
	}

	/**
	 * 运算的类型
	 */
	private enum AirthType {
		ADD("add", 0), DIVIDE("divide", 1), SUBTRACT("subtract", 2), MULTIPLY("multiply", 3);
		private int value;

		AirthType(String key, int value) {
			this.value = value;
		}

		public int getValue() {
			return value;
		}
	}

	/**
	 * 
	 * @Title: Arith
	 * @Description: 求平均数
	 * @param arr
	 * @return 
	 * @throws
	 */
	public static double average(int[] arr) {
		return Arrays.stream(arr).average().getAsDouble();
		
	}
	
	/**
	 * 
	 * @Title: Arith
	 * @Description: 最大公约数
	 * @param numbers
	 * @return 
	 * @throws
	 */
	public static OptionalInt gcd(int[] numbers) {
	    return Arrays.stream(numbers)
	            .reduce((a, b) -> gcd(a, b));
	}

	/**
	 * 
	 * @Title: Arith
	 * @Description: 最小公倍数
	 * @param numbers
	 * @return 
	 * @throws
	 */
	public static OptionalInt lcm(int[] numbers) {
	    IntBinaryOperator lcm = (x, y) -> (x * y) / gcd(x, y);
	    return Arrays.stream(numbers)
	            .reduce((a, b) -> lcm.applyAsInt(a, b));
	}

	private static int gcd(int a, int b) {
	    if (b == 0) {
	        return a;
	    }
	    return gcd(b, a % b);
	}
	
	/**
	 * 
	 * @Title: Arith
	 * @Description: 检查数字是否时偶数
	 * @param value
	 * @return 
	 * @throws
	 */
	public static boolean isEven(final int value) {
	    return (value & 0b1) == 0;
	}

	public static void main(String[] args) {
		System.out.println(multiplys(2, 2.56, 5));
		System.out.println(2.56 + 2.56);
		System.out.println(getRandomNum(0.1, 0.5));
	}
	/**
	   *获得两个数值之间的随机数
	 * @param min
	 * @param max
	 * @return
	 */
	public static Double getRandomNum(double min,double max){
		int minNum = (int) (min * 100);
		int maxNum = (int) (max * 100);
		Random random = new Random();
        int s = random.nextInt(maxNum)%(maxNum-minNum+1) + minNum;
        return divides(2,s,100);
	}

}
